/* shape {id,src,x,y}
* event {aftershapeposchange(selShape),afteraddshape(addedShape),afterremoveshape(removedShape),afterselectshape(selShape),afterResizeCanvas(),inResizeCanvas()}
*/
var cvtools = function(cfg) {
	Ext.applyIf(cfg,{aftershapeposchange:Ext.emptyFn,afteraddshape:Ext.emptyFn,afterremoveshape:Ext.emptyFn
		,afterselectshape:Ext.emptyFn,afterResizeCanvas:Ext.emptyFn,inResizeCanvas:Ext.emptyFn});
	var self = this;
	this.canvas = cfg.el;
	this.context = this.canvas.dom.getContext('2d');
	self.context.strokeStyle = 'blue';
	this.shapes = cfg.shapes || [];
	this.clear = function() {
		this.context.clearRect(0,0,this.canvas.dom.width,this.canvas.dom.height);
	}
	function drawImage(shape) {
		if(shape.x < 0) shape.x = 0;
		if(shape.y < 0) shape.y = 0;
		var rw = self.canvas.dom.width - shape.image.width;
		var rh = self.canvas.dom.height - shape.image.height;
		if(shape.x > rw) shape.x = rw;
		if(shape.y > rh) shape.y = rh;
		self.context.drawImage(shape.image,shape.x,shape.y);
	}
	self.init = function() {
		for(var i = 0 ; i < self.shapes.length; i++) {
			(function(index) {
				var image = new Image();
				var s = self.shapes[index];
				image.src = s.src;
				image.onload = function() {
					s.image = this;
					drawImage(s);
				}
				image.onerror = function() {
					self.shapes.splice(index,1);
				}
			})(i);
		}
		selShape = null;
	}

	this.draw = function(isInInner) {
		this.clear();
		if(isInInner) {
			for(var i = 0 ; i < this.shapes.length; i++) {
				self.context.drawImage(this.shapes[i].image,this.shapes[i].x,this.shapes[i].y);
			}
		} else {
			for(var i = 0 ; i < this.shapes.length; i++) {
				drawImage(this.shapes[i]);
			}
		}
	}
	
	self.setWH = function(w,h) {
		if(w != -1) { 
			self.canvas.dom.width = w;
		}
		if(h != -1) { 
			self.canvas.dom.height = h;
		}
		self.draw(true);
	}
	
	self.getWH = function() {
		return [self.canvas.dom.width,self.canvas.dom.height];
	}
	
	self.getSelectShape = function() {
		return selShape;
	}
	self.addShape = function(shape,flag) {
		if(flag) {
			for(var i = 0 ; i < self.shapes.length ; i++) {
				var s = self.shapes[i];
				if(s.id == shape.id) {
					selShape = self.shapes.splice(i, 1)[0];
					self.shapes.push(selShape);
					self.draw();
					drawSelectBorder();
					return;
				}
			}
		}
		var image = new Image();
		image.src = shape.src;
		image.onload = function() {
			shape.image = this;
			shape.x = parseInt(shape.x);
			shape.y = parseInt(shape.y);
			self.shapes.push(shape);
			selShape = shape;
			self.draw();
			drawSelectBorder();
			cfg.afteraddshape(selShape,self);
		}
	}
	self.selectShape = function(id) {
		for(var i = 0 ; i < self.shapes.length ; i++) {
			var s = self.shapes[i];
			if(s.id == id) {
				selShape = self.shapes.splice(i, 1)[0];
				self.shapes.push(selShape);
				self.draw();
				drawSelectBorder();
				cfg.afterselectshape(selShape,self);
				return;
			}
		}
	}
	self.removeShape = function(id) {
		if(id == undefined && selShape != null) {
			var s = self.shapes.pop();
			selShape = null;
			self.draw();
			cfg.afterremoveshape(s,self);
			return s;
		}
		if(id != undefined) {
			for(var i = 0,len = self.shapes.length ; i < len ; i++) {
				if(self.shapes[i].id == id) {
					var s = self.shapes.splice(i,1)[0];
					if(selShape != null && s.id == selShape.id) {
						selShape = null;
					}
					self.draw();
					cfg.afterremoveshape(s,self);
					return s;
				}
			}
		}
	}
	
	var mousePressed = false;
	var mouseXY = [0,0];
	var selShape = null;
	var deviation = 2;
	var moveAttr = {
		x:false,
		y:false,
		xy:false
	};
	var resizePressed = false;
	
	function getClickImage(posXY) {
		var index = -1;
		for(var i = self.shapes.length -1 ;i >=0 ;i--) {
			var s = self.shapes[i];
			var pos = findOffset(self.canvas.dom);
			var x = posXY[0] - pos[0] - s.x;
			var y = posXY[1] - pos[1] - s.y;
			if(x > 0 && x < s.image.width && y > 0 && y < s.image.height) {
				index = i;
				break;
			}
		}
		return index;
	}
	this.canvas.on('mousedown',function(e,t) {
		mouseXY = e.xy;
		if(e.ctrlKey) {
			var i = getClickImage(e.xy);
			if(i != -1) {
				selShape = self.shapes.splice(i, 1)[0];
				self.shapes.push(selShape);
				self.draw();
				cfg.afterselectshape(selShape,self);
			}
		} else if(selShape != null){
			var pos = findOffset(self.canvas.dom);
			var x = e.xy[0]- pos[0] - selShape.x;
			var y = e.xy[1]- pos[1] - selShape.y;
			if(x > 0 && x < selShape.image.width && y > 0 && y < selShape.image.height) {
				mousePressed = true;
			}
		}
		drawSelectBorder();
	});
	
	this.canvas.on('dblclick',function(e,t) {
		mouseXY = e.xy;
		var i = getClickImage(e.xy);
		if(i != -1) {
			selShape = self.shapes.splice(i, 1)[0];
			self.shapes.push(selShape);
			self.draw();
			drawSelectBorder();
			cfg.afterselectshape(selShape,self);
		}
	});
	
	function drawSelectBorder() {
		if(selShape != null) {
			self.context.strokeRect(selShape.x-2,selShape.y-2,selShape.image.width+4,selShape.image.height+4);
		}
	}
	this.canvas.on('mouseup',function(e,t) {
		mousePressed = false;
		if(selShape!=null) cfg.aftershapeposchange(selShape,self);
	});
	
	this.canvas.on('mousemove',function (e,t) {
		if(mousePressed) {
			selShape.x += e.xy[0] - mouseXY[0];
			selShape.y += e.xy[1] - mouseXY[1];
			mouseXY = e.xy;
			self.draw();
		}
	});
	
	Ext.getBody().on('keydown',function(e,t) {
		if(e.keyCode >= 37 && e.keyCode <= 40) {
			switch (e.keyCode) {
				case 37: 
					selShape.x -= 1;
					break;
				case 38: 
					selShape.y -= 1;
					break;
				case 39: 
					selShape.x += 1;
					break;
				case 40: 
					selShape.y += 1;
					break;
			}
			self.draw();
			cfg.aftershapeposchange(selShape,self);
			return;
		}
		if(e.keyCode == 27 || e.keyCode == 82) {
			selShape = null;
			self.draw();
			return;
		}
		if(e.keyCode == 46) {
			self.removeShape();
		}
	});
	
	var oldCursorStyle = 'default';
	Ext.getBody().on({
		'mousemove':function(e,t) {
			if(resizePressed) {
				var pos = findOffset(self.canvas.dom);
				var x = e.xy[0]- pos[0];
				var y = e.xy[1]- pos[1];
				if(moveAttr.x) {
					self.setWH(x,-1);
				} else if(moveAttr.y) {
					self.setWH(-1,y);
				} else if(moveAttr.xy) {
					self.setWH(x,y);
				}
				cfg.inResizeCanvas();
			} else {
				var pos = findOffset(self.canvas.dom);
				if(!pos) return;
				var x = e.xy[0]- pos[0];
				var y = e.xy[1]- pos[1];
				var wh = self.getWH();
				if(x >= wh[0] - deviation && x <= wh[0] + deviation) {
					moveAttr.x = true;
					self.canvas.setStyle("cursor","e-resize");
				} else {
					moveAttr.x = false;
				}
				if(y >= wh[1] - deviation && y <= wh[1] + deviation) {
					moveAttr.y = true;
					self.canvas.setStyle("cursor","n-resize");
				} else {
					moveAttr.y = false;
				}
				if(moveAttr.x && moveAttr.y) {
					moveAttr.x = false;
					moveAttr.y = false;
					moveAttr.xy = true;
					self.canvas.setStyle("cursor","nw-resize");
				} else {
					moveAttr.xy = false;
				}
				if(moveAttr.x||moveAttr.y||moveAttr.xy) {
					var tmpCursorStyle = self.canvas.getStyle('cursor');
					if(!(tmpCursorStyle == 'e-resize' || tmpCursorStyle == 'n-resize' || tmpCursorStyle == 'nw-resize')) {
						oldCursorStyle = tmpCursorStyle;
					} 
				} else {
					self.canvas.setStyle("cursor",oldCursorStyle);
				}
			}
		},
		'mousedown':function(e,t) {
			if(moveAttr.x || moveAttr.y || moveAttr.xy) {
				resizePressed = true;
			} else {
				resizePressed = false;
			}
		},
		'mouseup':function(e,t) {
			if(resizePressed) {
				cfg.afterResizeCanvas();
				resizePressed = false;
			}
		},
		scope:Ext.getBody()
	});
	
	function findOffset(obj) {
		var curX = curY = 0;
		if (obj.offsetParent) {
			do {
				curX += obj.offsetLeft;
				curY += obj.offsetTop;
			} while (obj = obj.offsetParent);
		return [curX,curY];
		}
	}
};